#include <functional>
#include <stdexcept>
#include "io_service_pool.hpp"

namespace easyasio {
namespace net {

io_service_pool::io_service_pool(std::size_t pool_size, bool usemultiloop)
	: next_io_service_(0),
      pool_size_(pool_size),
      usemultiloop_(usemultiloop)
{
	if (pool_size == 0)
		throw std::runtime_error("io_service_pool size is 0");

    std::size_t service_num = usemultiloop ? pool_size : 1;
	for (std::size_t i = 0; i < service_num; ++i)
	{
		io_service_ptr io_service(new asio::io_service);
		work_ptr work(new asio::io_service::work(*io_service));
		io_services_.push_back(io_service);
	    work_.push_back(work);
	}
}

void io_service_pool::run()
{
	std::vector<std::shared_ptr<std::thread> > threads;
	for (std::size_t i = 0; i < pool_size_; ++i)
	{
        io_service_ptr service = usemultiloop_ ? io_services_[i] : io_services_[0];
		std::shared_ptr<std::thread> thread = std::make_shared<std::thread>( [=]()->void { service->run(); });
		threads.push_back(thread);
	}

	for (std::size_t i = 0; i < threads.size(); ++i)
	    threads[i]->join();
}

void io_service_pool::stop()
{
	for (std::size_t i = 0; i < io_services_.size(); ++i)
		io_services_[i]->stop();
}

asio::io_service& io_service_pool::get_io_service()
{
    if (!usemultiloop_)
        return *io_services_[0];

	asio::io_service& io_service = *io_services_[next_io_service_];
	++next_io_service_;
	if (next_io_service_ == io_services_.size())
	    next_io_service_ = 0;
	return io_service;
}

}//net  
}//easyasio  
